from django.views.generic import View
from config_app.models import EnvironmentModel
from ..models import CaseModel, PubParamModel, CaseResultModel, CaseSetModel, CaseSetDetailModel
from ..forms import ExecuteForm
from .extractor import Extract
from utils.messages import Json_Response, Form_Invalid
from interface_test_app import tasks
from utils.record import record
from utils.logger import logger
import json
import time
import traceback


# todo 根据项目管理用户，用户仅可操作项目内的数据

class ExecuteView(View):
    extract = Extract()
    logger = logger()

    def _get_pb_value(self, param_list):
        # 查询公共参数值
        result = []
        for obj in PubParamModel.objects.filter(name__in=param_list):
            result.append({
                'name': obj.name,
                'value': obj.value
            })
        return result

    def _replace_pub(self, iter):
        # todo 参数为json的用例，格式化的值只能是str
        # json.dumps->replace->json.loads
        string = json.dumps(iter)
        param_list = self.extract.get_pub_param(string)  # 获取公共参数
        to_value = self._get_pb_value(param_list)
        for item in to_value:
            string = self.extract.set_pub_param(item['name'], item['value'], string)
        to_python = json.loads(string)
        return to_python

    def _construct_request(self, env_id, obj: CaseModel):
        protocol, server, url, redirect = obj.protocol, obj.server, obj.url, obj.redirect
        if not server:
            env_obj = EnvironmentModel.objects.get(id=env_id)
            server = '{}:{}'.format(env_obj.host, env_obj.port)
        headers, params, data, json = {}, {}, {}, {}
        [headers.setdefault(item['key'], item['value']) for item in obj.headers]
        [params.setdefault(item['key'], item['value']) for item in obj.param_data]
        [data.setdefault(item['key'], item['value']) for item in obj.form_data]
        [json.setdefault(item['key'], item['value']) for item in obj.json_data]

        req_info = {
            'url': '{}://{}{}'.format(protocol, server, url),
            'method': obj.method,
            'params': params,
            'data': data,
            'json': json,
            'headers': headers,
            'allow_redirects': redirect
        }
        return self._replace_pub(req_info)

    def _construct_assert(self, obj: CaseModel):
        (assert_status,
         assert_headers,
         assert_json,
         ) = (
            obj.assert_status,
            obj.assert_headers,
            obj.assert_json,
        )
        assert_info = {
            'assert_status': assert_status,
            'assert_headers': assert_headers,
            'assert_json': assert_json
        }
        return self._replace_pub(assert_info)

    # 调试当个用例，同步任务
    def execute_case(self, request):
        form = ExecuteForm.Case(request)
        if form.is_valid():
            data = form.cleaned_data
            id = data.pop('id')
            env_id = data.pop('env_id')
            qs = CaseModel.objects.filter(id=id)
            if not qs:
                return Json_Response(code=201, err_msg='用例失效')
            obj = qs[0]
            req_info = self._construct_request(env_id, obj)
            assert_info = self._construct_assert(obj)
            result = tasks.execute_case({
                'case_id': id,
                'req_info': req_info,
                'assert_info': assert_info,
                'user_id': None
            })
            record(request, 14, obj)
            return Json_Response(msg='调试完成', data=result)
        else:
            return Form_Invalid(form)

    def execute_CaseSet(self, request):
        self.logger.info('请求开始')
        form = ExecuteForm.CaseSet(request)
        if form.is_valid():
            self.logger.info('表单验证通过')
            data = form.cleaned_data
            id = data.pop('id')  # set_id
            env_id = data.pop('env_id')
            case_infos = []
            for obj in CaseSetDetailModel.objects.filter(set__id=id).values_list('case__id', named=True):
                case_obj = CaseModel.objects.get(id=obj.case__id)
                case_info = {
                    'case_id': case_obj.id,
                    'req_info': self._construct_request(env_id, case_obj),
                    'assert_info': self._construct_assert(case_obj),
                    'user_id': None
                }
                case_infos.append(case_info)
            self.logger.info('{},{},{}'.format(id, env_id, case_infos))
            try:
                tasks.execute_case_set.apply_async(kwargs={
                    'set_info': {
                        'set_id': id,
                        'case_infos': case_infos
                    }
                })
            except:
                self.logger.error(traceback.format_exc())

            return Json_Response(msg='任务创建成功')

        else:
            return Form_Invalid(form)
